package com.uh.checking.proc;


import com.uh.checking.config.FileFilterCfg;
import com.uh.checking.config.SubJarConfig;
import com.uh.checking.filter.IncludeMatchFilter;

import java.io.File;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import static com.uh.checking.proc.JarCheckingUtils.execute;
import static com.uh.checking.config.JarCheckingConstants.*;

public class SubJarProcessor {

    private SubJarConfig subJarConf;

    private File libsDir;

    public SubJarProcessor(SubJarConfig subJarConf, MainJarProcessor mainProcessor) {
        this.subJarConf = subJarConf;
        this.libsDir = new File(mainProcessor.getUnzipDir(), mainProcessor.getConfig().getPathLibs());
    }

    public void process() {
        FileFilterCfg filter = subJarConf.getIncludeFilter();
        String[] jarNames = libsDir.list(new IncludeMatchFilter(filter.getPerfix(), filter.getSubfix()));
        for (String jarName : jarNames)
        {
            File jarFile = new File(libsDir, jarName);
            processJar(jarFile);
        }
    }



    /**
     * 重构Jar包，会进行下面操作：
     */
    private void processJar(File jarFile) {
        System.out.println("Processing Jar: " + jarFile + ", exists:" + jarFile.exists());
        String jarName = jarFile.getName();
        File jarDir = jarFile.getParentFile();
        File unzipDir = new File(jarDir, jarName.substring(0, jarName.length() - 4));//去除 .jar 后缀，作为解压目录

        for(String step : subJarConf.getSteps()) {
            switch (step) {
                case "clean":
                    //如果解压目录已经存在就删除后再重建
                    if(unzipDir.exists() == true) {
                        execute(CMD_RM + unzipDir.getPath());
                    }
                    unzipDir.mkdir();//新建jar包的解压目录
                    break;
                case "unzip":
                    System.out.println("unzipDir:" + unzipDir.getAbsolutePath());
                    execute("cd " + unzipDir.getPath() + " && jar -xvf ../" + jarName);//对jar进行解压
                    break;
                case "process":
                    //删除目录
                    if(subJarConf.getDeleteFiles() != null) {
                        for(String delFile : subJarConf.getDeleteFiles()) {
                            File mavenDir = new File(unzipDir, delFile);
                            if (mavenDir.exists()) {
                                execute(CMD_RM + mavenDir.getPath());
                            }
                        }
                    }

                    //修改META-INF/MANIFEST.MF文件
                    processManifest(jarFile, unzipDir);
                    break;
                case "zip":
                    //重新打包 jar 文件
                    execute("jar -cvfM " + jarFile.getPath() + " -C " + unzipDir.getPath() + " ." );

                    break;
                case "cleanProcess":
                    //删除过程中的解压目录
                    execute(CMD_RM + unzipDir.getPath());

                    break;
                case "rename":
                    //对文件进行更名操作
                    String[] replace = subJarConf.getReplace();
                    if(replace != null && replace.length == 2) {
                        renameJarFile(jarFile, replace[0], replace[1]);
                    }
                    break;
            }
        }

    }


    private void processManifest(File jarFile, File unzipDir)
    {
        String[] includeKeys =  subJarConf.getManifestIncludeKeys();
        if(includeKeys != null && includeKeys.length > 0) {
            File manifestFile = new File(unzipDir, "META-INF/MANIFEST.MF");
            if (manifestFile.exists() == false) {
                throw new RuntimeException("MANIFEST.MF not existed! In jar: " + jarFile.getAbsolutePath());
            }

            Set<String> includeKeySet = new HashSet<>(subJarConf.getManifestIncludeKeys().length);
            Collections.addAll(includeKeySet, subJarConf.getManifestIncludeKeys());

            //找到 not includes keys(removingNames)
            Manifest mf = JarCheckingUtils.readManifext(manifestFile);
            Attributes attrs = mf.getMainAttributes();
            List<Attributes.Name> removingNames = new ArrayList<>();
            for (Object name : attrs.keySet()) {
                Attributes.Name aName = (Attributes.Name) name;
                if (includeKeySet.contains(aName.toString()) == false) {
                    removingNames.add(aName);
                }
            }

            //删除not includes keys
            for (Attributes.Name removeName : removingNames) {
                attrs.remove(removeName);
            }

            //写会到原文件
            JarCheckingUtils.wirteManifest(mf, manifestFile);
        }
    }


    private void renameJarFile(File orgFile, String prefix, String renamedPrefix) {
        File parent = orgFile.getParentFile();
        String name = orgFile.getName();

        String renamed = name.replace(prefix, renamedPrefix);
        File renameTo = new File(parent, renamed);
        orgFile.renameTo(renameTo);
        System.out.println("Jar File rename from: " + orgFile.toString() + ", to: " + renameTo.toString());
    }


}
